local Character = {}

local character_object = {
	position = { 0, 0 },
	animations = {
		idle = {
			startFrame = 1,
			frameCount = 9,
			time = 0.1,
			mode = MOAITimer.LOOP
		},
		
		run = {
			startFrame = 41,
			frameCount = 16,
			time = 0.03,
			mode = MOAITimer.LOOP
		},
		
		jump = {
			startFrame = 89,
			frameCount = 3,
			time = 0.1,
			mode = MOAITimer.NORMAL
		},
	},

}

function Character:initialize(layer)

	self.deck = ResourceManager:get('character')
	self.prop = MOAIProp2D.new()
	self.prop:setDeck(self.deck)
	self.prop:setLoc(unpack(character_object.position) )
	layer:insertProp (self.prop)
	self.remapper = MOAIDeckRemapper.new ()
	 -- just remapping 1 index, char anim frame
	self.remapper:reserve (1)
	-- assign remapper to prop
	self.prop:setRemapper( self.remapper )
	
	self.animations = {}
	-- parse all animations defined inside character_object
	-- and create necessary animations
	for name, def in pairs ( character_object.animations ) do
	
		self:addAnimation( name, def.startFrame, def.frameCount,
			def.time, def.mode )
		
	end


	--self:startAnimation('run')
	self:startAnimation('idle')
	self:initializePhysics()
end

function Character:initializePhysics()
	
	-- create object to store body and shapes
	self.physics = {}
	-- add a dynamic body to simulation
	-- the body of the character
	self.physics.body =
		PhysicsManager.world:addBody ( MOAIBox2DBody.DYNAMIC )
	-- position the body using the same initial position
	-- as the rendered character
	self.physics.body:setTransform (
		unpack ( character_object.position ) )
		
	-- add a square same size as sprite (64 x 64)
	-- would want a more customized size to make
	-- collisions more realistic to the sprite
	-- picture
	self.physics.fixture = self.physics.body:addRect(-32,-32,32,32)
	
	self.prop:setParent(self.physics.body)
	
	-- setup a callback to be executed when box2d detects a
	-- collision with the player's shape
	self.physics.fixture:setCollisionHandler( onCollide,
		MOAIBox2DArbiter.BEGIN )

end

function Character:run (direction, keyDown)
	
	if keyDown then
		-- set sprite scale based on direction
		-- negative scales flip the image
		self.prop:setScl( direction, 1 )
		velX, velY = self.physics.body:getLinearVelocity()
		self.physics.body:setLinearVelocity(direction * 100,
			velY)
		-- if not already running and not jumping then start
		-- the run animation
		if (self.currentAnimation ~= self:getAnimation( 'run ') )
			and not self.jumping then
			
			self:startAnimation('run')		
		
		end	
		
	else
			if not self.jumping then
				self:stopMoving()
			end
	end
end

function Character:moveLeft( keyDown )
	self:run ( -1, keyDown )
end

function Character:moveRight( keyDown )
	self:run (1, keyDown )
end

function Character:stopMoving()
	-- if we're not jumping, stop movement of both axes
	-- and start the idle animation
	if not self.jumping then
		self.physics.body:setLinearVelocity( 0 , 0 )
		self:startAnimation( 'idle' )
	end
end

function Character:jump( keyDown )
	if keyDown and not self.jumping then
		self.physics.body:applyForce(0, 8000)
		self.jumping = true
		self:startAnimation( 'jump' )
	end
end

function Character:stopJumping()
	self.jumping = false
	self:stopMoving ()
end

function onCollide ( phase, fixtureA, fixtureB, arbiter )
	-- if the shape we collide with is the floor, stop jumping
	if Game:belongsToScene(fixtureB) then
		
		Character:stopJumping()
	
	end

end

function Character:addAnimation( name, startFrame, frameCount, time, mode )
	
	local curve = MOAIAnimCurve.new ()
	
	curve:reserveKeys( 2 )
	-- vvv key number, time (0 for start), key value (start frame),
	-- vvv key value (animation curve to use)
	curve:setKey ( 1, 0, startFrame, MOAIEaseType.LINEAR )
	-- time = time between frames(dt) * frameCount
	-- end frame = startFrame + total frames
	curve:setKey ( 2, time*frameCount, startFrame + frameCount,
		MOAIEaseType.LINEAR )
		
	-- the above two functions create a linear function from
	-- startFrame at time 0 to startFrame + frameCount
	-- at the end of the curve
	
	-- create our animation
	local anim = MOAIAnim:new()
	-- reserve one link that will be used to connect
	-- curve to the remapper
	anim:reserveLinks(1)
	-- connect the two
	anim:setLink( 1, curve, self.remapper, 1 )
	
	-- when we start the animation, it will iterate through
	-- the curve, passing the result of the curve to the
	-- remapper. when this happens, the remapper will change
	-- the image displayed by the prop. 
	-- at the end of the call is the index of the remapper
	-- we will be using, since only 1 is reserved, 1 is passed
	
	-- set the defined animation mode
	anim:setMode (mode)
	-- store the animation under the param name
	self.animations[name] = anim		
	
end

-- return indexed animation
function Character:getAnimation( name )
	return self.animations[name]
end

-- stop the anim currently running if it exists
function Character:stopCurrentAnimation ()

	if self.currentAnimation then
		self.currentAnimation:stop()
		
	end

end

-- starts the anim.. duh
function Character:startAnimation( name )
	-- stopping current anim is really important,
	-- if not stopped, leads to an infinite anim
	-- playing memory leak style situation
	-- due to stacking animations
	self:stopCurrentAnimation()
	
	-- get the animation indexed by name
	self.currentAnimation = self:getAnimation (name)
	
	-- start animation
	self.currentAnimation:start()
	
	-- return it, incase we want to do something with it later
	-- like blocking blocking the coroutine to chain
	-- multiple animations
	return self.currentAnimation
	
end




return Character